Merge And Rebase
Lets start off by creating some more commits and adding them to master
. This way our branches will diverge, meaning they have commits that are unique in both and have a common ancestor, A
.
Please add D
and E
in the README.md.
Desired State:
Git Merge And Rebaseβ
A commit
is a point in time with a specific state of the entire code base.
We have work done, but its on another branch. We need to get it back into our main branch, master
but how?
There really is only one strategy to merge
code from one branch to another, but depending on the history, different outcomes can happen. rebase
can help put a branch into a clean
state.
What is Mergeβ
A merge
is attempt to combine two histories together that have diverged (branched) at some point in the past. There is a common commit
point between the two, this is referred to as the Lowest Common Ancestor (LCA
which is also referred as "merge base"
often in the docs).
To put it simply, the first common parent, is the LCA
.
git then merges the sets of commits onto the merge base and creates a new commit at the tip of the branch
that is being merged on with all the changes combined into one commit.
How to Mergeβ
Merging is quite simple.
Merging will merge changes from source
to target
The branch you are currently on is the target
branch and the branch you name in <branch_name>
will be the source branch.
git merge <branch_name>
Given the following state, merge foo
onto master
. Since we want to keep foo and master
in its current state for other problems later in this lesson. Please start by branching off of master
. I named mine master-foo
.
Finally, when you are done use git log to see the resulting state of master-foo
.
Git state should be
You can see merge commit have 3 parents because of how 3-way merge happens (ORT is enhanced version of 3-way merge algorithm)
- Create the following git setup. (not full graph). Make changes in
bar.md
- Now try to merge
bar
ontomaster
Wait here there are no new merge commit. Why ??
Because of linear history, as there is no need add an extra commit. We can just Fast-Forward (FF
) our pointer to latest commit.
What will happen if we have some untracked changes in repo, and we checkout to some other branch and we push the changesβ
What about even if the changes are trackedβ
Evil Mergeβ
an
evil merge
is something that makes changes that came from neither side and aren't actually resolving a conflict.β Linus Torvalds (creator of Git and Linux)
It basically means, do not add extra things while merging because this extra change will not be present in any history.
example:
-
initial state
let x = 3;
let y = 4; -
Change From Remote A
let x = 3;
let y = 4;
x++ -
Change From Remote B
let x = 3;
let y = 4;
y-- -
But after merging somehow we git this
let x = 3+1000; // <-- evil merge
let y = 4;
x++
y--
Our merging algorithm allow this but please do not do this, it is strictly prohibited in many orgs.
Rebaseβ
Rebasing often gets a bad wrap. Part of this is because people don't really know why or when to use rebase
and will end up using it incorrectly and thus yelling on the twitters that it "ruins their entire life.".
with the following setup
We can demonstrate the power of rebase
. What rebase
will do is update foo
to having base Y
instead of A
.
But why do we need it ?
rebase
helps in take new changes committed to the branch from where we have branched. And because of this now we can do fast-forward merge
.
What rebase does isβ
The basic steps of rebase is the following:
- execute git rebase
<targetbranch>
. I will refer to the current branch as<currentbranch>
later on - checkout the
<targetbranch>
. - play one commit at a time from
<currentbranch>
- once finished will update
<currentbranch>
to the current commit sha
Pros:
it make history clean because there is no merging and thus every merge is
Fast-Forward
merge
Cons:
it changes the history of a branch. That means that if you already had
foo
on a remote git, you would have toforce push
it to theremote
again to rewrite history there as well.
NEVER CHANGE HISTORY OF A PUBLIC BRANCH. In other words, don't ever change history of master
.
But for your own personal branch ? I don't think it matters and i think having a nice clean history can be very beneficial if you use git to search for changes through time.